
#ifndef  __KC_FEKCAB_OP_LOG_HPP_2010__
#define  __KC_FEKCAB_OP_LOG_HPP_2010__

#include <vector>
#include <string>
#include <fstream>

#include "bocat/common/lrucache.hpp"

#include "timestamp.hpp"

#include "recloc.hpp"
#include "record.hpp"
#include "oplogiter.hpp"


namespace   fekcab   {

class   OpLog
{

public	:
	static	const std::string	OP_PUT;
	static	const std::string	OP_GET;
	static	const std::string	OP_DEL;

public	:
	OpLog( const std::string data_dir, u_int32_t file_rotate_size=0, int32_t slim = 0, const char* key_encode = NULL, const char* value_encode = NULL );
	~OpLog();

public  :
	int	log( const Timestamp& ts, const std::string& op, const std::string& kpin, const std::string& key, const std::string& value );

public	:
	OpLogIterator*	getSlimOpLogIterator( void );
	void		freeSlimOpLogIterator( OpLogIterator*, bool done=true );
	std::string		getSlimmingFile( void ) const { return _file_slimming; }
	int				getSlimmingFileNo( void ) const { return _fileno_slimming; }

	int		clearDataDirectory( void );
	int		clearDataDirectory( const char* backup_dir );

public	:
	// if there are oplogs to checkpoint/restore
	bool	isClear( void );

	// calculate size of oplog ( in bytes )
	int		getTankage( void );

public	:
	void	beginRecovery( void );
	void	endRecovery( void );
	bool	hasMoreRecoveryIterator( void );
	OpLogIterator*	getNextRecoveryIterator( void );

private	:
	void	initialize();
	void	finalize();

	void	scanDataDirectory( void );

	int		setCurrentFileID( uint32_t id );
	int		getCurrentFileID( void );

	int		getFileToSlim( std::string& file_to_slim );
	int		getFileNoFromName(const std::string&);


	std::string		getNextAppendFileName( void );
	std::string		getCurrentAppendFileName( void );
	std::string		getAppendFileName( void );
	std::string		getFileName( u_int32_t fileno );
	std::string		getReadFileName( u_int32_t fileno );

	std::ofstream&	openAppendFile( void );
	std::ifstream&	openReadFile( u_int32_t fileno );
	void			closeAllReadFiles( void );
	
private	:
	std::string	_data_dir;

	u_int32_t	_file_rotate_size;
	int32_t		_slim;

private	:
	int32_t		_slim_lowater;
	bool		_slimming;

	int			countFiles( void );


private :
	std::ofstream	_ofs_append;

	u_int32_t	_min_fileno;
	u_int32_t	_max_fileno;

	static const std::string	SLICE_BASENAME;
	static const u_int32_t		MIN_SLICE_SIZE_THRESHOLD;
	static const u_int32_t		MAX_SLICE_SIZE_THRESHOLD;

	// cache for read only file handles
	typedef	std::ifstream*	ifsp_type;
	typedef	bocat::common::LRUCache< u_int32_t, ifsp_type >	ifsp_cache_type;

	ifsp_cache_type	_ifsp_cache;
	boost::mutex	_ifsp_cache_mutex;

	OpLogIterator*	_index_iterator_p;
	boost::mutex	_index_iterator_mutex;
	std::string		_file_slimming;
	int				_fileno_slimming;

	const char*	_key_encode;
	const char*	_value_encode;
	bool	_key_encode_base64_b;
	bool	_value_encode_base64_b;

private	:
	std::vector< std::string >	_filelist_recovery;
	size_t		_filelist_index_recovery;

};  //// class OpLog

}   ////    namespace   fekcab

#endif  ////    __KC_FEKCAB_OP_LOG_HPP_2010__

